package org.example.user.service.impl;

import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.QueryWrapper;
import io.micrometer.common.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.example.common.config.BusinessException;
import org.example.user.dto.AssignAclDTO;
import org.example.user.dto.CreateRoleDTO;
import org.example.user.dto.RoleQueryDTO;
import org.example.user.dto.UpdateRoleDTO;
import org.example.user.entity.SysRoleAclEntity;
import org.example.user.mapper.SysRoleAclMapper;
import org.example.user.vo.SysRoleVO;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.example.user.service.ISysRoleService;
import org.example.user.entity.SysRoleEntity;
import org.example.user.mapper.SysRoleMapper;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 角色表 服务层实现。
 *
 * @author mybatis-flex-helper automatic generation
 * @since 1.0
 */
@Service
@Slf4j
public class SysRoleServiceImpl extends ServiceImpl<SysRoleMapper, SysRoleEntity> implements ISysRoleService {

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private SysRoleAclMapper sysRoleAclMapper;

@Transactional
@Override
public int createRole(CreateRoleDTO createRoleDTO) {
    SysRoleEntity sysRoleEntity = new SysRoleEntity();
    BeanUtils.copyProperties(createRoleDTO, sysRoleEntity);
    sysRoleEntity.setIsDelete(0);
    sysRoleEntity.setCreatedBy("admin");
    sysRoleEntity.setCreatedTime(new Date());
    sysRoleMapper.insert(sysRoleEntity);

    if (createRoleDTO.getAclIds() != null && createRoleDTO.getAclIds().length > 0) {
        List<SysRoleAclEntity> roleAclEntities = Arrays.stream(createRoleDTO.getAclIds())
                .map(aclId -> {
                    SysRoleAclEntity entity = new SysRoleAclEntity();
                    entity.setRoleId(sysRoleEntity.getId());
                    entity.setAclId(aclId);
                    entity.setCreatedTime(new Date());
                    return entity;
                })
                .collect(Collectors.toList());

        // 检查 role_id 和 acl_id 的组合是否唯一
        Set<String> uniqueKeys = roleAclEntities.stream()
                .map(entity -> entity.getRoleId() + ":" + entity.getAclId())
                .collect(Collectors.toSet());

        if (uniqueKeys.size() != roleAclEntities.size()) {
            throw new BusinessException("角色权限组合存在重复");
        }

        log.info("Inserting role-acl entities: {}", roleAclEntities);
        sysRoleAclMapper.insertBatch(roleAclEntities);
    }

    return 1;
}


    @Override
    public int updateRole(UpdateRoleDTO updateRoleDTO) {
        SysRoleEntity sysRoleEntity = sysRoleMapper.selectOneById(updateRoleDTO.getRoleId());
        if (sysRoleEntity == null) {
            throw new BusinessException("角色不存在");
        }
        BeanUtils.copyProperties(updateRoleDTO, sysRoleEntity);
        sysRoleMapper.update(sysRoleEntity);

        // 更新角色权限
        if (updateRoleDTO.getAclIds() != null) {
            QueryWrapper queryWrapper = new QueryWrapper();
            queryWrapper.eq("role_id", updateRoleDTO.getRoleId());
            sysRoleAclMapper.deleteByQuery(queryWrapper);

            List<SysRoleAclEntity> roleAclEntities = Arrays.stream(updateRoleDTO.getAclIds())
                    .map(aclId -> {
                        SysRoleAclEntity entity = new SysRoleAclEntity();
                        entity.setRoleId(updateRoleDTO.getRoleId());
                        entity.setAclId(aclId);
                        entity.setCreatedTime(new Date());
                        return entity;
                    })
                    .collect(Collectors.toList());
            sysRoleAclMapper.insertBatch(roleAclEntities);
        }

        return 1;
    }

    @Override
    public int deleteRole(Long roleId) {
        SysRoleEntity sysRoleEntity = sysRoleMapper.selectOneById(roleId);
        if (sysRoleEntity == null) {
            throw new BusinessException("角色不存在");
        }
        sysRoleMapper.delete(sysRoleEntity);
        log.info("删除角色，roleId: {}", roleId);
        return 1;
    }

    @Override
    public Page<SysRoleVO> pageList(RoleQueryDTO roleQueryDTO) {
        QueryWrapper queryWrapper = new QueryWrapper();
        if (!StringUtils.isEmpty(roleQueryDTO.getName())) {
            queryWrapper.like(SysRoleEntity::getName, roleQueryDTO.getName());
        }
        if (!StringUtils.isEmpty(roleQueryDTO.getCode())) {
            queryWrapper.like(SysRoleEntity::getCode, roleQueryDTO.getCode());
        }

        Page<SysRoleEntity> paginate = sysRoleMapper.paginate(roleQueryDTO.getPage(), roleQueryDTO.getSize(), queryWrapper);

        List<SysRoleEntity> records = paginate.getRecords();
        List<SysRoleVO> roleVOS = records.stream().map(this::convertToVO).collect(Collectors.toList());

        Page<SysRoleVO> page = new Page<>();
        page.setRecords(roleVOS);
        page.setTotalRow(paginate.getTotalRow());
        page.setTotalPage(paginate.getTotalPage());
        page.setPageNumber(paginate.getPageNumber());
        page.setPageSize(paginate.getPageSize());

        return page;
    }

    private SysRoleVO convertToVO(SysRoleEntity entity) {
        SysRoleVO vo = new SysRoleVO();
        BeanUtils.copyProperties(entity, vo);
        return vo;
    }

    @Override
    public SysRoleVO getRoleDetail(Long roleId) {
        SysRoleEntity sysRoleEntity = sysRoleMapper.selectOneById(roleId);
        if (sysRoleEntity == null) {
            throw new BusinessException("角色不存在");
        }
        SysRoleVO roleVO = convertToVO(sysRoleEntity);

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("role_id", roleId);
        List<SysRoleAclEntity> roleAclEntities = sysRoleAclMapper.selectListByQuery(queryWrapper);
        List<Long> aclIds = roleAclEntities.stream().map(SysRoleAclEntity::getAclId).collect(Collectors.toList());
        roleVO.setAclIds(aclIds);

        return roleVO;
    }

    @Override
    public void assignAcl(AssignAclDTO assignAclDTO) {
        Long roleId = assignAclDTO.getRoleId();
        Long[] aclIds = assignAclDTO.getAclIds();

        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("role_id", roleId);
        sysRoleAclMapper.deleteByQuery(queryWrapper);

        if (aclIds != null && aclIds.length > 0) {
            List<SysRoleAclEntity> roleAclEntities = Arrays.stream(aclIds)
                    .map(aclId -> {
                        SysRoleAclEntity entity = new SysRoleAclEntity();
                        entity.setRoleId(roleId);
                        entity.setAclId(aclId);
                        entity.setCreatedTime(new Date());
                        return entity;
                    })
                    .collect(Collectors.toList());
            sysRoleAclMapper.insertBatch(roleAclEntities);
        }
    }
}
